package entityManager;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;

import org.xml.sax.SAXException;

import settings.IdManager;

import dataStorage.DataHandler;
import dataStorage.DataXML;

import entity.Category;
import entity.Expense;
import entity.Income;
import exception.NullVariableFound;

//@author A0105110J
public class CategoryManager implements Manager<Category> {

	private ArrayList<Category> allCategoriesList;
	private final String fileKey = "category";

	public CategoryManager() throws TransformerConfigurationException,
			InstantiationException, IllegalAccessException, JAXBException,
			ParserConfigurationException, SAXException, IOException,
			TransformerException {
		loadAll();
	}

	public void loadAll() throws TransformerConfigurationException,
			InstantiationException, IllegalAccessException, JAXBException,
			ParserConfigurationException, SAXException, IOException,
			TransformerException {
		DataHandler dataHandler = DataXML.getInstance();
		allCategoriesList = dataHandler.load(fileKey, Category.class);
	}

	public boolean add(Category _target) throws IOException, JAXBException,
			TransformerConfigurationException, ParserConfigurationException,
			SAXException, TransformerException, InstantiationException,
			IllegalAccessException {

		DataHandler dataHandler = DataXML.getInstance();
		if (getByName(_target.getName()) == null) {
			if (dataHandler.write(_target, fileKey, Category.class)) {
				System.out.println("Category Write Success");
				return true;
								
			} else{
				System.out.println("Category Write Fail");
				return false;
			}
		} else {
			System.out.println("Category Exists");
			return false;
		}
	}

	public boolean remove(Category _target) throws IOException, JAXBException,
			TransformerConfigurationException, ParserConfigurationException,
			SAXException, TransformerException, InstantiationException,
			IllegalAccessException, NullVariableFound {
		// parse the object to Expense
		DataHandler dataHandler = DataXML.getInstance();
		ExpenseManager em = new ExpenseManager();
		IncomeManager im = new IncomeManager();
		System.out.println("no of expenses/incomes with that category (should be 0):" +em.getByCategory(_target).size() + "  ::  "
				+ im.getByCategory(_target).size());
		if ((em.getByCategory(_target).size() == 0)
				&& im.getByCategory(_target).size() == 0) {
			if (dataHandler.remove(_target, fileKey)) {
				System.out.println("Category Remove Success");
				return true;
			} else {
				System.out.println("Category Fail");
				return false;
			}
		} else {
			System.out.println("Category " + _target.getId() + ", " + _target.getName() + " cannot be deleted: has elements");
			return false;
		}

	}

	public boolean update(Category _target)throws IOException, JAXBException,
	TransformerConfigurationException, ParserConfigurationException,
	SAXException, TransformerException, InstantiationException,
	IllegalAccessException, NullVariableFound {
		DataHandler dataHandler = DataXML.getInstance();
		if (dataHandler.update(_target.getId(), _target, fileKey,
				Category.class)) {
			ExpenseManager em = new ExpenseManager();
			IncomeManager im = new IncomeManager();
			ArrayList<Expense> aEx = em.getByCategory(_target);
			for (int i=0;i<aEx.size();i++){
				aEx.get(i).getCategory().setName(_target.getName());
				em.update(aEx.get(i));
			}
			ArrayList<Income> aIn = im.getByCategory(_target);
			for (int i=0;i<aIn.size();i++){
				aIn.get(i).getCategory().setName(_target.getName());
				im.update(aIn.get(i));
			}			
			System.out.println("Update Success");
			return true;
		} else {
			System.out.println("Update Fail");
		}
		return false;
	}

	public Category getById(String _id)
			throws TransformerConfigurationException, InstantiationException,
			IllegalAccessException, JAXBException,
			ParserConfigurationException, SAXException, IOException,
			TransformerException {
		loadAll();
		Iterator<Category> lt = allCategoriesList.iterator();
		Category temp;

		while (lt.hasNext()) {
			temp = lt.next();
			if (temp.getId().equalsIgnoreCase(_id))
				return temp;
		}

		return null;
	}

	public Category getByName(String _name)
			throws TransformerConfigurationException, InstantiationException,
			IllegalAccessException, JAXBException,
			ParserConfigurationException, SAXException, IOException,
			TransformerException {
		loadAll();
		Iterator<Category> lt = allCategoriesList.iterator();
		Category temp;

		while (lt.hasNext()) {
			temp = lt.next();
			if (temp.getName().equalsIgnoreCase(_name))
				return temp;
		}
		return null;
	}

	public ArrayList<Category> getByKeyword(String _keyword)
			throws TransformerConfigurationException, InstantiationException,
			IllegalAccessException, JAXBException,
			ParserConfigurationException, SAXException, IOException,
			TransformerException {
		loadAll();
		ArrayList<Category> matchList = new ArrayList<Category>();

		Iterator<Category> it = allCategoriesList.iterator();
		Category curr;
		while (it.hasNext()) {
			curr = it.next();
			if (curr.getName().toLowerCase().indexOf(_keyword.toLowerCase()) != -1) {
				matchList.add(curr);
			}
		}
		return matchList;
	}

	public ArrayList<Category> getAll()
			throws TransformerConfigurationException, InstantiationException,
			IllegalAccessException, JAXBException,
			ParserConfigurationException, SAXException, IOException,
			TransformerException {
		loadAll();
		return allCategoriesList;
	}

}
